#include "BinaryOpWidget.h"

#define OP_OR    0
#define OP_AND   1
#define OP_NOR   2
#define OP_NAND  3
#define OP_XOR   4
#define OP_PLUS  5
#define OP_MINUS 6
#define OP_MULT  7
#define OP_DIV   8

BinaryOpWidget::BinaryOpWidget(QWidget *parent, BitArray *arr0, BitArray *arr1)
    : QWidget(parent), array0(arr0), array1(arr1)
{
    QHBoxLayout *hLayout = new QHBoxLayout(this);
    pBtnOr = new QPushButton("OR");
    pBtnAnd = new QPushButton("AND");
    pBtnNor = new QPushButton("NOR");
    pBtnNand = new QPushButton("NAND");
    pBtnXor = new QPushButton("XOR");
    pBtnPlus = new QPushButton("+");
    pBtnMinus = new QPushButton("-");
    pBtnMult = new QPushButton("*");
    pBtnDiv = new QPushButton("/");

    pBtnOr->setMinimumWidth(20);
    pBtnAnd->setMinimumWidth(20);
    pBtnNor->setMinimumWidth(20);
    pBtnNand->setMinimumWidth(20);
    pBtnXor->setMinimumWidth(20);
    pBtnPlus->setMinimumWidth(20);
    pBtnMinus->setMinimumWidth(20);
    pBtnMult->setMinimumWidth(20);
    pBtnDiv->setMinimumWidth(20);

    pBtnOr->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnAnd->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnNor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnNand->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnXor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnPlus->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnMinus->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnMult->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    pBtnDiv->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);

    pBtnOr->setCheckable(true);
    pBtnAnd->setCheckable(true);
    pBtnNor->setCheckable(true);
    pBtnNand->setCheckable(true);
    pBtnXor->setCheckable(true);
    pBtnPlus->setCheckable(true);
    pBtnMinus->setCheckable(true);
    pBtnMult->setCheckable(true);
    pBtnDiv->setCheckable(true);

    pBtnOr->setChecked(true);
    currOp = OP_OR;
    updateButtons();

    hLayout->insertStretch(0);
    hLayout->addWidget(pBtnOr);
    hLayout->addWidget(pBtnAnd);
    hLayout->addWidget(pBtnNor);
    hLayout->addWidget(pBtnNand);
    hLayout->addWidget(pBtnXor);
    hLayout->addWidget(pBtnPlus);
    hLayout->addWidget(pBtnMinus);
    hLayout->addWidget(pBtnMult);
    hLayout->addWidget(pBtnDiv);
    hLayout->insertStretch(-1);
    hLayout->setContentsMargins(5,0,5,0);

    connect(pBtnOr, SIGNAL(pressed()), this, SLOT(opOr()));
    connect(pBtnAnd, SIGNAL(pressed()), this, SLOT(opAnd()));
    connect(pBtnNor, SIGNAL(pressed()), this, SLOT(opNor()));
    connect(pBtnNand, SIGNAL(pressed()), this, SLOT(opNand()));
    connect(pBtnXor, SIGNAL(pressed()), this, SLOT(opXor()));
    connect(pBtnPlus, SIGNAL(pressed()), this, SLOT(opPlus()));
    connect(pBtnMinus, SIGNAL(pressed()), this, SLOT(opMinus()));
    connect(pBtnMult, SIGNAL(pressed()), this, SLOT(opMult()));
    connect(pBtnDiv, SIGNAL(pressed()), this, SLOT(opDiv()));
}

void BinaryOpWidget::updateButtons()
{
//    pBtnOr->setChecked(false);
//    pBtnAnd->setChecked(false);
//    pBtnNor->setChecked(false);
//    pBtnNand->setChecked(false);
//    pBtnXor->setChecked(false);
//    pBtnPlus->setChecked(false);
//    pBtnMinus->setChecked(false);
//    pBtnMult->setChecked(false);
//    pBtnDiv->setChecked(false);

    if(currOp != OP_OR)
        pBtnOr->setChecked(false);
    if(currOp != OP_AND)
        pBtnAnd->setChecked(false);
    if(currOp != OP_NOR)
        pBtnNor->setChecked(false);
    if(currOp != OP_NAND)
        pBtnNand->setChecked(false);
    if(currOp != OP_XOR)
        pBtnXor->setChecked(false);
    if(currOp != OP_PLUS)
        pBtnPlus->setChecked(false);
    if(currOp != OP_MINUS)
        pBtnMinus->setChecked(false);
    if(currOp != OP_MULT)
        pBtnMult->setChecked(false);
    if(currOp != OP_DIV)
        pBtnDiv->setChecked(false);
}

void BinaryOpWidget::opOr()
{
    currOp = OP_OR;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opAnd()
{
    currOp = OP_AND;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opNor()
{
    currOp = OP_NOR;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opNand()
{
    currOp = OP_NAND;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opXor()
{
    currOp = OP_XOR;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opPlus()
{
    currOp = OP_PLUS;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opMinus()
{
    currOp = OP_MINUS;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opMult()
{
    currOp = OP_MULT;
    updateButtons();
    emit operationChanged();
}

void BinaryOpWidget::opDiv()
{
    currOp = OP_DIV;
    updateButtons();
    emit operationChanged();
}

BitArray BinaryOpWidget::operate()
{
    BitArray ret;
    switch(currOp)
    {
    case OP_OR:    ret = *array0 | *array1; break;
    case OP_AND:   ret = *array0 & *array1; break;
    case OP_NOR:   ret = ~(*array0 | *array1); break;
    case OP_NAND:  ret = ~(*array0 & *array1); break;
    case OP_XOR:   ret = *array0 ^ *array1; break;
    case OP_PLUS:  ret = *array0 + *array1; break;
    case OP_MINUS: ret = *array0 - *array1; break;
    case OP_MULT:  ret = *array0 * *array1; break;
    case OP_DIV:   ret = *array0 / *array1; break;
    default: break;
    }
    return ret;
}
